/**
 * 项目名：化工企业安全生产信息化管理平台
 * 日期：    2020-03-01 22:19:07
 * Copyright (c) 2015- -版权所有
 */

package com.joysuch.wwyt.edu.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import javax.transaction.Transactional;

import com.joysuch.wwyt.bp.enums.DocTypes;
import com.joysuch.wwyt.common.enums.CommonTypes;
import com.joysuch.wwyt.common.enums.CoursewareStates;
import com.joysuch.wwyt.common.service.CommonTypeService;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.common.util.PageDataUtils.PageDataConvert;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.BusinessRestrictionsException;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.BaseAttachmentRepositoryService;
import com.joysuch.wwyt.core.service.BaseImageRepositoryService;
import com.joysuch.wwyt.core.service.BizCodeGeneratorFacade;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.edu.bean.EduCoursewareDetailBean;
import com.joysuch.wwyt.edu.bean.EduCoursewareEditBean;
import com.joysuch.wwyt.edu.bean.EduCoursewareListBean;
import com.joysuch.wwyt.edu.bean.EduCoursewareListBean.SearchEduCourseware;
import com.joysuch.wwyt.edu.entity.EduCourseware;
import com.joysuch.wwyt.edu.entity.dsl.QEduCourseCourseware;
import com.joysuch.wwyt.edu.entity.dsl.QEduCourseware;
import com.joysuch.wwyt.edu.mapper.EduCoursewareMapper;
import com.joysuch.wwyt.edu.repository.EduCourseCoursewareDao;
import com.joysuch.wwyt.edu.repository.EduCourseLearnHistoryDao;
import com.joysuch.wwyt.edu.repository.EduCoursewareDao;
import com.joysuch.wwyt.edu.service.EduCourseCoursewareService;
import com.joysuch.wwyt.edu.service.EduCoursewareService;
import com.joysuch.wwyt.util.DocTypeUtils;
import com.querydsl.core.types.EntityPath;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

@Service
@Transactional
public class EduCoursewareServiceImpl implements EduCoursewareService {

    @Autowired
    private EduCoursewareDao dao;
    @Autowired
    private BizCodeGeneratorFacade bizCodeGeneratorFacade;
    @Autowired
    private CommonTypeService commonTypeService;
    @Autowired
    private BaseAttachmentRepositoryService attachmentService;
    @Autowired
    private BaseImageRepositoryService imageRepositoryService;
    @Autowired
    private EduCourseCoursewareService courseCoursewareService;
    @Autowired
    private EduCourseCoursewareDao courseCoursewareDao;
    @Autowired
    private BaseUserDao baseUserDao;
    @Autowired
    private JPAQueryFactory jpaQueryFactory;

    @Autowired
    private EduCourseLearnHistoryDao eduCourseLearnHistoryDao;

    @Autowired
    private EduCoursewareMapper coursewareMapper;

    @Override
    public EduCourseware add(EduCoursewareEditBean entity) {
        EduCourseware content = new EduCourseware();
        Assert.isTrue(dao.countOfName(entity.getName()) == 0, String.format("名称[%s]已经存在", entity.getName()));
        if (StringUtils.isNotBlank(entity.getCode())) {
            Assert.isTrue(dao.countOfCode(entity.getCode()) == 0, String.format("编号%s已经存在", entity.getCode()));
            content.setCode(entity.getCode());
        } else {
            content.setCode(bizCodeGeneratorFacade.keJian());
        }
        BeanUtils.copyProperties(entity, content, "id", "code", "coverId");
        if (entity.getAttachment() != null&&StringUtils.isNotBlank(entity.getAttachment().getName())) {
            content.setAttachmentId(entity.getAttachment().getId());
            content.setFormat(FilenameUtils.getExtension(entity.getAttachment().getName()));
            content.setDocType(DocTypeUtils.getDocType(content.getFormat(), DocTypes.DOC.getCode()));
        }
        if (entity.getCover() != null) {
            content.setCoverId(entity.getCover().getId());
        }
        content.setState(CoursewareStates.INITIAL.getId());
        content.setCreateUserName(baseUserDao.getBaseUserNameById(Context.getCurrentUserId()));
        dao.save(content);
        commonTypeService.updateTypeCount(CommonTypes.COURSEWARE, content.getTypeId());
        return content;
    }

    @Override
    public void update(EduCoursewareEditBean entity) {
        Assert.isTrue(dao.countOfNameExcludeId(entity.getName(), entity.getId()) == 0,
                String.format("名称[%s]已经存在", entity.getName()));
        EduCourseware content = dao.findById(entity.getId()).get();
        Long oldTypeId = content.getTypeId();
        Long newTypeId = entity.getTypeId();
        // Assert.notNull(entity.getCode(), "编号不能为空");
        // Assert.isTrue(dao.countOfCodeExcludeId(entity.getCode(), entity.getId()) == 0,
        // String.format("编号%s已经存在", entity.getCode()));
        // content.setCode(entity.getCode());
        BeanUtils.copyProperties(entity, content, "id", "code");
        if (entity.getAttachment() != null&&StringUtils.isNotBlank(entity.getAttachment().getName())) {
            content.setAttachmentId(entity.getAttachment().getId());
            content.setFormat(FilenameUtils.getExtension(entity.getAttachment().getName()));
            content.setDocType(DocTypeUtils.getDocType(content.getFormat(), DocTypes.DOC.getCode()));
        }else {
            content.setFormat("");
            content.setDocType("");
            content.setAttachmentId(null);
        }
        if (entity.getCover() != null) {
            content.setCoverId(entity.getCover().getId());
        }
        content.setUpdateTime(new Date());
        dao.save(content);
        if (!Objects.equals(oldTypeId, newTypeId)) {
            commonTypeService.updateTypeCount(CommonTypes.COURSEWARE, newTypeId);
            commonTypeService.updateTypeCount(CommonTypes.COURSEWARE, oldTypeId);
        }
    }

    @Override
    public Page<EduCoursewareListBean> findByPage(Pageable page, SearchEduCourseware condition) {
        Predicate predicate = prepareListSearchCondition(condition);

        return findByPage(page, predicate);
    }

    public Page<EduCoursewareListBean> findByPage(Pageable page, Predicate predicate) {
        Page<EduCourseware> data = predicate == null ? dao.findAll(page) : dao.findAll(predicate, page);
        return convertPageData(data);
    }

    private Predicate prepareListSearchCondition(SearchEduCourseware condition) {
        Predicate p = null;
        QEduCourseware q = QEduCourseware.eduCourseware;
        if (condition.getNameOrCode() != null) {
            p = ExpressionUtils.and(p, ExpressionUtils.or(q.code.contains(condition.getNameOrCode()),
                    q.name.contains(condition.getNameOrCode())));
        }
        if (condition.getCode() != null) {
            p = ExpressionUtils.and(p, q.code.contains(condition.getCode()));
        }
        if (condition.getName() != null) {
            p = ExpressionUtils.and(p, q.name.contains(condition.getName()));
        }
        if (condition.getTypeId() != null) {
            p = ExpressionUtils.and(p, q.typeId.eq(condition.getTypeId()));
        }
        if (condition.getDocType() != null) {
            p = ExpressionUtils.and(p, q.docType.eq(condition.getDocType()));
        }
        if (condition.getState() != null) {
            p = ExpressionUtils.and(p, q.state.eq(condition.getState()));
        }
        if(condition.getTypeName()!=null){
            p=ExpressionUtils.and(p,q.typeId.eq(condition.getTypeName()));
        }
        return p;
    }

    @Override
    public void delete(Long id) throws BusinessRestrictionsException {
        // 校验业务逻辑是否允许删除。如本数据被其他业务关联，删除后导致其他业务不可用。不能删除时将抛出业务异常
        checkBussinessRestrictions(id);
        EduCourseware one = dao.getOne(id);
        dao.deleteById(id);
        if (one.getTypeId() != null) {
            commonTypeService.updateTypeCount(CommonTypes.COURSEWARE, one.getTypeId());
        }
    }

    /**
     * 校验业务逻辑是否允许删除。如本数据被其他业务关联，删除后导致其他业务不可用
     *
     * @param id
     *            要删除的业务ID
     *             抛出的业务异常
     */
    private void checkBussinessRestrictions(Long id) {
        List<Long> courseIds= coursewareMapper.selectCourseIds(id);
        if (coursewareMapper.selectTrainingCourse(courseIds)>0){
            throw new IllegalArgumentException("该课件所属的课程已被培训关联，无法删除课件");
        }
        // 删除此课件在所有课程中的关联
        courseCoursewareService.deleteByCoursewareId(id);
    }

    @Override
    public EduCourseware findById(Long id) {
        return dao.findById(id).orElse(null);
    }

    @Override
    public EduCoursewareDetailBean getById(Long id) {
        EduCourseware entity = findById(id);
        if (entity == null) {
            return null;
        }
        EduCoursewareDetailBean bean = new EduCoursewareDetailBean();
        BeanUtils.copyProperties(entity, bean);
        bean.setStateName(CoursewareStates.findNameById(entity.getState()));
        bean.setTypeName(commonTypeService.getNameById(entity.getTypeId()));
        if (entity.getAttachmentId() != null) {
            bean.setAttachment(attachmentService.findByIdIntoBean(entity.getAttachmentId()));
        }
        if (entity.getCoverId() != null) {
            bean.setCover(imageRepositoryService.findBeanById(entity.getCoverId()));
        }
        bean.setCreateUserId(entity.getCreateBy());
        bean.setDocTypeName(DocTypes.findNameByCode(entity.getDocType()));

        if (entity.getDocType() != null){
            if (entity.getDocType().equals(DocTypes.DOC.getCode()) || entity.getDocType().equals(DocTypes.IMAGE.getCode())){
                bean.setType(1);
            }
            if (entity.getDocType().equals(DocTypes.VIDEO.getCode()) || entity.getDocType().equals(DocTypes.AUDIO.getCode())){
                bean.setType(0);
            }
        }else{
            bean.setType(1);
        }
        return bean;
    }

    public void audit(Long id, CoursewareStates state, String remark) {
        dao.findById(id).ifPresent(cw -> {
            cw.setState(state.getId());
            cw.setAuditMsg(remark);
            cw.setUpdateTime(new Date());
            dao.save(cw);
        });
    }

    @Override
    public Page<EduCoursewareListBean> findAuditByPage(Pageable page, SearchEduCourseware condition) {
        condition.setState(null);
        Predicate predicate = prepareListSearchCondition(condition);
        predicate = ExpressionUtils.and(predicate,
                QEduCourseware.eduCourseware.state.gt(CoursewareStates.INITIAL.getId()));
        Page<EduCourseware> data = dao.findAll(predicate, page);

        return convertPageData(data);
    }

    /**
     * @param data
     * @return
     */
    protected Page<EduCoursewareListBean> convertPageData(Page<EduCourseware> data) {
        return PageDataUtils.convertPageData(data, new PageDataConvert<EduCoursewareListBean, EduCourseware>() {

            @Override
            public EduCoursewareListBean convert(EduCourseware f) {
                EduCoursewareListBean bean = new EduCoursewareListBean();
                BeanUtils.copyProperties(f, bean);
                bean.setTypeName(commonTypeService.getNameById(f.getTypeId()));
                bean.setDocTypeName(DocTypes.findNameByCode(f.getDocType()));
                bean.setStateName(CoursewareStates.findNameById(f.getState()));
                if (f.getCoverId() != null) {
                    bean.setCover(imageRepositoryService.findBeanById(f.getCoverId()));
                }
                return bean;
            }

        });
    }

    @Override
    public void applyForAudit(Long id) {
        EduCourseware one = dao.getOne(id);
        Assert.isTrue(one.getState() == CoursewareStates.AUDIT_FAILED.getId()
                || one.getState() == CoursewareStates.INITIAL.getId(), "课件当前状态不可以审核");
        one.setState(CoursewareStates.WAITING_FOR_AUDIT.getId());
        dao.save(one);
    }

    @Override
    public Page<EduCoursewareDetailBean> findCoursecenterPage(Long courseId, Long coursewareTypeId, Pageable page) {
        QEduCourseware qc = QEduCourseware.eduCourseware;
        QEduCourseCourseware cc = QEduCourseCourseware.eduCourseCourseware;
        List<EntityPath> fromList = new ArrayList<>(2);
        fromList.add(qc);
        List<Predicate> where = new ArrayList<>(2);
        // 只有绑定了课程的课件，才可以在课程中心里显示
        fromList.add(cc);
        where.add(cc.coursewareId.eq(qc.id));
        if (courseId != null) {
            where.add(cc.courseId.eq(courseId));
        }
        if (coursewareTypeId != null) {
            where.add(qc.typeId.eq(coursewareTypeId));
        }
        JPAQuery<EduCourseware> query = jpaQueryFactory.select(qc).from(fromList.toArray(new EntityPath[0]))
                .where(where.toArray(new Predicate[0])).distinct();
        PageImpl<EduCourseware> re = null;
        if (page != null) {
            long count = query.fetchCount();
            query.offset(page.getOffset()).limit(page.getPageSize());
            List<EduCourseware> list = query.fetch();
            re = new PageImpl<>(list, page, count);
        } else {
            List<EduCourseware> list = query.fetch();
            re = new PageImpl<>(list);
        }
        return PageDataUtils.convertPageData(re, new PageDataConvert<EduCoursewareDetailBean, EduCourseware>() {

            @Override
            public EduCoursewareDetailBean convert(EduCourseware f) {
                EduCoursewareDetailBean bean = new EduCoursewareDetailBean();
                BeanUtils.copyProperties(f, bean);
                bean.setTypeName(commonTypeService.getNameById(f.getTypeId()));
                if (f.getAttachmentId() != null) {
                    bean.setAttachment(attachmentService.findByIdIntoBean(f.getAttachmentId()));
                    bean.setViewUrl(parseViewUrl(f.getAttachmentId()));
                }
                if (f.getCoverId() != null) {
                    bean.setCover(imageRepositoryService.findBeanById(f.getCoverId()));
                }
                Integer num;
//                if (DocTypes.DOC.getCode().equals(f.getDocType()) || DocTypes.IMAGE.getCode().equals(f.getDocType())) {
//                    num = eduCourseLearnHistoryDao.countByCoursewareIdAndUserId(f.getId(), Context.getCurrentUserId());
//                } else {
//                    num = eduCourseLearnHistoryDao.findByIdsAndState(f.getId(), Context.getCurrentUserId());
//                }
                num = eduCourseLearnHistoryDao.findByIdsAndState(f.getId(), Context.getCurrentUserId());

                bean.setVideoState((num != null && num > 0) ? 1 : 0);
                return bean;
            }
        });
    }

    protected String parseViewUrl(Long attachmentId) {
        return "/doc/preview?id=" + attachmentId;
    }
}
